package com.zxy.ziems.server.energy.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zxy.btp.common.exception.ConditionException;
import com.zxy.btp.common.response.PageResult;
import com.zxy.ziems.server.board.constant.BoardConstant;
import com.zxy.ziems.server.constant.DateType;
import com.zxy.ziems.server.constant.enums.DeviceStatusDictItemEnum;
import com.zxy.ziems.server.constant.enums.DictCodeEnum;
import com.zxy.ziems.server.device.controller.DeviceTreeVO;
import com.zxy.ziems.server.device.pojo.entity.DataTypeEntity;
import com.zxy.ziems.server.device.pojo.entity.DataUnitEntity;
import com.zxy.ziems.server.device.pojo.entity.DeviceEntity;
import com.zxy.ziems.server.device.pojo.entity.DevicePropertyEntity;
import com.zxy.ziems.server.device.service.DataTypeService;
import com.zxy.ziems.server.device.service.DataUnitService;
import com.zxy.ziems.server.device.service.DevicePropertyService;
import com.zxy.ziems.server.device.service.DeviceService;
import com.zxy.ziems.server.domain.DeviceMeasureData;
import com.zxy.ziems.server.domain.DeviceMeasureDataIncrementHour;
import com.zxy.ziems.server.domain.DictItem;
import com.zxy.ziems.server.domain.User;
import com.zxy.ziems.server.dto.DeviceMeasureDataExtendDTO;
import com.zxy.ziems.server.dto.DeviceMeasureDateGroupDto;
import com.zxy.ziems.server.energy.mapper.DeviceMeasureDataDayMapper;
import com.zxy.ziems.server.energy.mapper.DeviceMeasureDataIncrementHourMapper;
import com.zxy.ziems.server.energy.mapper.DeviceMeasureDataMapper;
import com.zxy.ziems.server.energy.pojo.dto.ClassifyDeviceEleDTO;
import com.zxy.ziems.server.energy.pojo.dto.DeviceMeasureDateDTO;
import com.zxy.ziems.server.energy.pojo.entity.DeviceMeasureDataDayEntity;
import com.zxy.ziems.server.energy.pojo.param.DeviceMeasureDataPageParam;
import com.zxy.ziems.server.energy.pojo.param.DeviceMeasureDataQParam;
import com.zxy.ziems.server.energy.pojo.vo.DeviceMeasureDataVO;
import com.zxy.ziems.server.energy.service.DeviceMeasureDataService;
import com.zxy.ziems.server.mybatis.core.service.ServiceImplX;
import com.zxy.ziems.server.service.DictItemService;
import com.zxy.ziems.server.service.UserService;
import com.zxy.ziems.server.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.YearMonth;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class DeviceMeasureDataServiceImpl extends ServiceImplX<DeviceMeasureDataMapper, DeviceMeasureData> implements DeviceMeasureDataService {
    @Value("${zxy.property.deviceMeasureData.startYear}")
    private Integer startYear;
    @Autowired
    private DeviceMeasureDataDayMapper deviceMeasureDataDayMapper;
    @Autowired
    private DeviceMeasureDataIncrementHourMapper deviceMeasureDataIncrementHourMapper;
    @Autowired
    public UserService userService;
    @Autowired
    private DeviceService deviceService;


    @Override
    public List<DeviceMeasureDateDTO> getAvg(String dateType, LocalDate start, LocalDate end, Set<String> deviceIds, String dataTypeId) {
        List<DeviceMeasureDateDTO> res = new ArrayList<>();

        if (dataVerify(start)) {
            return res;
        }

        long days = ChronoUnit.DAYS.between(start, end);
        // 不同类型，统计分组不同
        if (dateType.equals(DateType.DAY)) {
            res = baseMapper.getDayAvg(start.getYear(), DateUtils.getStartTime(start), DateUtils.getEndTime(start),
                    new ArrayList<>(deviceIds), dataTypeId, "HOUR");
        } else if (dateType.equals(DateType.WEEK)) {
            res = baseMapper.getAvg(start.getYear(), DateUtils.getStartTime(start), DateUtils.getEndTime(start.plusDays(6)),
                    new ArrayList<>(deviceIds), dataTypeId, "DATE");
        } else if (dateType.equals(DateType.MONTH)) {
            res = baseMapper.getAvg(start.getYear(), DateUtils.getStartTime(start), DateUtils.getEndTime(YearMonth.from(start).atEndOfMonth()),
                    new ArrayList<>(deviceIds), dataTypeId, "DATE");
        } else if (dateType.equals(DateType.YEAR)) {
            res = baseMapper.getAvg(start.getYear(), DateUtils.getStartTime(start), DateUtils.getEndTime(LocalDate.of(start.getYear(), 12,
                    31)), new ArrayList<>(deviceIds), dataTypeId, "MONTH");
        } else if (dateType.equals(DateType.HIS_YEAR)) {
            // 历年
            int year = start.getYear();
            while (year <= end.getYear() && year <= LocalDate.now().getYear()) {
                List<DeviceMeasureDateDTO> tmp = baseMapper.getAvg(year, DateUtils.getStartTime(start), DateUtils.getEndTime(LocalDate.of(end.getYear(),
                        12, 31)), new ArrayList<>(deviceIds), dataTypeId, "YEAR");
                res.add(tmp.get(0));
                year++;
            }
        } else if (dateType.equals(DateType.CUSTOM)) {
            // 天最多支持90天
//            if (days > 90) {
//                throw new ConditionException("天统计最多90天");
//            }
            res = baseMapper.getAvg(start.getYear(), DateUtils.getStartTime(start), DateUtils.getEndTime(end),
                    new ArrayList<>(deviceIds), dataTypeId, "DATE");
        } else {
            throw new ArithmeticException("不支持此类型");
        }
        dateStrChange(dateType, res);
        return res;
    }

    private void dateStrChangeNew(String dateType, List<DeviceMeasureDateGroupDto> list) {

        if (dateType.equals(DateType.DAY)) {
            list.forEach(m -> m.setDayStr(String.format("%02d:00", Integer.valueOf(m.getDayStr()))));
        } else if (dateType.equals(DateType.WEEK)) {

        } else if (dateType.equals(DateType.MONTH)) {

        } else if (dateType.equals(DateType.YEAR)) {
            list.forEach(m -> m.setDayStr(LocalDate.now().getYear() + String.format("-%02d", Integer.valueOf(m.getDayStr()))));
        } else if (dateType.equals(DateType.HIS_YEAR)) {

        } else if (dateType.equals(DateType.CUSTOM)) {

        }
    }

    /**
     * 峰平谷 日期格式化
     *
     * @param dateType
     * @param list
     */
    private void dateStrChangeNewEle(String dateType, List<ClassifyDeviceEleDTO> list) {

        if (dateType.equals(DateType.DAY)) {
            list.forEach(m -> m.setDayStr(String.format("%02d:00", Integer.valueOf(m.getDayStr()))));
        } else if (dateType.equals(DateType.WEEK)) {

        } else if (dateType.equals(DateType.MONTH)) {

        } else if (dateType.equals(DateType.YEAR)) {
            list.forEach(m -> m.setDayStr(LocalDate.now().getYear() + String.format("-%02d", Integer.valueOf(m.getDayStr()))));
        } else if (dateType.equals(DateType.HIS_YEAR)) {

        } else if (dateType.equals(DateType.CUSTOM)) {

        }
    }

    private void dateStrChange(String dateType, List<DeviceMeasureDateDTO> list) {

        if (dateType.equals(DateType.DAY)) {
            list.forEach(m -> m.setDayStr(String.format("%02d:00", Integer.valueOf(m.getDayStr()))));
        } else if (dateType.equals(DateType.WEEK)) {

        } else if (dateType.equals(DateType.MONTH)) {

        } else if (dateType.equals(DateType.YEAR)) {
            list.forEach(m -> m.setDayStr(LocalDate.now().getYear() + String.format("-%02d", Integer.valueOf(m.getDayStr()))));
        } else if (dateType.equals(DateType.HIS_YEAR)) {

        } else if (dateType.equals(DateType.CUSTOM)) {

        }
    }

    @Override
    public List<DeviceMeasureDateDTO> getSum(String dateType, LocalDate start, LocalDate end, Set<String> deviceIds, String dataTypeId) {
        List<DeviceMeasureDateDTO> res = new ArrayList<>();
        if (dataVerify(start)) {
            return res;
        }
        long days = ChronoUnit.DAYS.between(start, end);
        // 不同类型，统计分组不同
        if (dateType.equals(DateType.DAY)) {
            res = baseMapper.getSum(start.getYear(), DateUtils.getStartTime(start), DateUtils.getEndTime(start),
                    new ArrayList<>(deviceIds), dataTypeId, "HOUR");
        } else if (dateType.equals(DateType.WEEK)) {
            res = baseMapper.getSum(start.getYear(), DateUtils.getStartTime(start), DateUtils.getEndTime(start.plusDays(6)),
                    new ArrayList<>(deviceIds), dataTypeId, "DATE");
        } else if (dateType.equals(DateType.MONTH)) {
            res = baseMapper.getSum(start.getYear(), DateUtils.getStartTime(start), DateUtils.getEndTime(YearMonth.from(start).atEndOfMonth()),
                    new ArrayList<>(deviceIds), dataTypeId, "DATE");
        } else if (dateType.equals(DateType.YEAR)) {
            res = baseMapper.getSum(start.getYear(), DateUtils.getStartTime(start), DateUtils.getEndTime(LocalDate.of(start.getYear(), 12,
                    31)), new ArrayList<>(deviceIds), dataTypeId, "MONTH");
        } else if (dateType.equals(DateType.HIS_YEAR)) {
            int year = start.getYear();
            while (year <= end.getYear() && year <= LocalDate.now().getYear()) {
                List<DeviceMeasureDateDTO> tmp = baseMapper.getSum(year, DateUtils.getStartTime(start), DateUtils.getEndTime(LocalDate.of(end.getYear(),
                        12, 31)), new ArrayList<>(deviceIds), dataTypeId, "YEAR");
                res.add(tmp.get(0));
                year++;
            }
        } else if (dateType.equals(DateType.CUSTOM)) {
            // 天最多支持90天
//            if (days > 90) {
//                throw new ConditionException("天统计最多90天");
//            }
            res = baseMapper.getSum(start.getYear(), DateUtils.getStartTime(start), DateUtils.getEndTime(end),
                    new ArrayList<>(deviceIds), dataTypeId, "DATE");
        } else {
            throw new ArithmeticException("不支持此类型");
        }
        dateStrChange(dateType, res);
        return res;
    }


    /**
     * 计算单位时间内，各个设备的能源
     *
     * @param dateType
     * @param start
     * @param end
     * @param deviceIds
     * @param dataTypeId
     * @return
     */
    @Override
    public List<DeviceMeasureDateGroupDto> getDeviceSum(String dateType, LocalDate start, LocalDate end, Set<String> deviceIds, String dataTypeId, List<String> classifyIds) {
        List<DeviceMeasureDateGroupDto> res = new ArrayList<>();
        if (dataVerify(start)) {
            return res;
        }
        long days = ChronoUnit.DAYS.between(start, end);
        // 不同类型，统计分组不同
        if (dateType.equals(DateType.DAY)) {
            res = baseMapper.getDeviceHourSum(start.getYear(), DateUtils.getStartTime(start), DateUtils.getEndTime(start),
                    new ArrayList<>(deviceIds), dataTypeId, "HOUR", classifyIds);
        } else if (dateType.equals(DateType.CUR_DAY)) {
            res = baseMapper.getDeviceSum(start.getYear(), DateUtils.getStartTime(start), DateUtils.getEndTime(start),
                    new ArrayList<>(deviceIds), dataTypeId, "DATE", classifyIds);
        } else if (dateType.equals(DateType.SEVEN_DAY)) {
            res = baseMapper.getDeviceHourSum(start.getYear(), DateUtils.getStartTime(start), DateUtils.getEndTime(start),
                    new ArrayList<>(deviceIds), dataTypeId, "HOUR", classifyIds);
        } else if (dateType.equals(DateType.WEEK)) {
            res = baseMapper.getDeviceSum(start.getYear(), DateUtils.getStartTime(start), DateUtils.getEndTime(start.plusDays(6)),
                    new ArrayList<>(deviceIds), dataTypeId, "DATE", classifyIds);
        } else if (dateType.equals(DateType.MONTH)) {
            res = baseMapper.getDeviceSum(start.getYear(), DateUtils.getStartTime(start), DateUtils.getEndTime(YearMonth.from(start).atEndOfMonth()),
                    new ArrayList<>(deviceIds), dataTypeId, "DATE", classifyIds);
        } else if (dateType.equals(DateType.CUR_MONTH)) {
            res = baseMapper.getDeviceSum(start.getYear(), DateUtils.getStartTime(start), DateUtils.getEndTime(YearMonth.from(start).atEndOfMonth()),
                    new ArrayList<>(deviceIds), dataTypeId, "MONTH", classifyIds);
        } else if (dateType.equals(DateType.YEAR)) {
            res = baseMapper.getDeviceSum(start.getYear(), DateUtils.getStartTime(start), DateUtils.getEndTime(LocalDate.of(start.getYear(), 12,
                    31)), new ArrayList<>(deviceIds), dataTypeId, "MONTH", classifyIds);
        } else if (dateType.equals(DateType.HIS_YEAR)) {
            int year = start.getYear();
            while (year <= end.getYear() && year <= LocalDate.now().getYear()) {
                List<DeviceMeasureDateGroupDto> tmp = baseMapper.getDeviceSum(year, DateUtils.getStartTime(start), DateUtils.getEndTime(LocalDate.of(end.getYear(),
                        12, 31)), new ArrayList<>(deviceIds), dataTypeId, "YEAR", classifyIds);
                res.add(tmp.get(0));
                year++;
            }
        } else if (dateType.equals(DateType.CUSTOM)) {
            // 天最多支持90天
//            if (days > 90) {
//                throw new ConditionException("天统计最多90天");
//            }
            res = baseMapper.getDeviceSum(start.getYear(), DateUtils.getStartTime(start), DateUtils.getEndTime(end),
                    new ArrayList<>(deviceIds), dataTypeId, "DATE", classifyIds);
        } else {
            throw new ArithmeticException("不支持此类型");
        }
        dateStrChangeNew(dateType, res);
        return res.stream().map(m -> {
            if (m.getStatistic() != null) {
                m.setStatistic(m.getStatistic().setScale(4, RoundingMode.HALF_UP));
            }
            if (m.getCost() != null) {
                m.setCost(m.getCost().setScale(4, RoundingMode.HALF_UP));
            }
            return m;
        }).collect(Collectors.toList());
    }

    /**
     * 计算单位时间内，各个设备的能源
     *
     * @param dateType
     * @param start
     * @param end
     * @param deviceIds
     * @param dataTypeId
     * @return
     */
    @Override
    public List<DeviceMeasureDateGroupDto> getDeviceRealSum(String dateType, LocalDate start, LocalDate end, Set<String> deviceIds, String dataTypeId, List<String> classifyIds) {
        List<DeviceMeasureDateGroupDto> res = new ArrayList<>();
        if (dataVerify(start)) {
            return res;
        }
        long days = ChronoUnit.DAYS.between(start, end);
        // 不同类型，统计分组不同
        if (dateType.equals(DateType.DAY)) {
            res = baseMapper.getDeviceHourRealSum(start.getYear(), DateUtils.getStartTime(start), DateUtils.getEndTime(start),
                    new ArrayList<>(deviceIds), dataTypeId, "HOUR", classifyIds);
        } else if (dateType.equals(DateType.CUR_DAY)) {
            res = baseMapper.getDeviceRealSum(start.getYear(), DateUtils.getStartTime(start), DateUtils.getEndTime(start),
                    new ArrayList<>(deviceIds), dataTypeId, "DATE", classifyIds);
        } else if (dateType.equals(DateType.SEVEN_DAY)) {
            res = baseMapper.getDeviceHourRealSum(start.getYear(), DateUtils.getStartTime(start), DateUtils.getEndTime(start),
                    new ArrayList<>(deviceIds), dataTypeId, "HOUR", classifyIds);
        } else if (dateType.equals(DateType.WEEK)) {
            res = baseMapper.getDeviceRealSum(start.getYear(), DateUtils.getStartTime(start), DateUtils.getEndTime(start.plusDays(6)),
                    new ArrayList<>(deviceIds), dataTypeId, "DATE", classifyIds);
        } else if (dateType.equals(DateType.MONTH)) {
            res = baseMapper.getDeviceRealSum(start.getYear(), DateUtils.getStartTime(start), DateUtils.getEndTime(YearMonth.from(start).atEndOfMonth()),
                    new ArrayList<>(deviceIds), dataTypeId, "DATE", classifyIds);
        } else if (dateType.equals(DateType.CUR_MONTH)) {
            res = baseMapper.getDeviceRealSum(start.getYear(), DateUtils.getStartTime(start), DateUtils.getEndTime(YearMonth.from(start).atEndOfMonth()),
                    new ArrayList<>(deviceIds), dataTypeId, "MONTH", classifyIds);
        } else if (dateType.equals(DateType.YEAR)) {
            res = baseMapper.getDeviceRealSum(start.getYear(), DateUtils.getStartTime(start), DateUtils.getEndTime(LocalDate.of(start.getYear(), 12,
                    31)), new ArrayList<>(deviceIds), dataTypeId, "MONTH", classifyIds);
        } else if (dateType.equals(DateType.HIS_YEAR)) {
            int year = start.getYear();
            while (year <= end.getYear() && year <= LocalDate.now().getYear()) {
                List<DeviceMeasureDateGroupDto> tmp = baseMapper.getDeviceRealSum(year, DateUtils.getStartTime(start), DateUtils.getEndTime(LocalDate.of(end.getYear(),
                        12, 31)), new ArrayList<>(deviceIds), dataTypeId, "YEAR", classifyIds);
                res.add(tmp.get(0));
                year++;
            }
        } else if (dateType.equals(DateType.CUSTOM)) {
            // 天最多支持90天
//            if (days > 90) {
//                throw new ConditionException("天统计最多90天");
//            }
            res = baseMapper.getDeviceRealSum(start.getYear(), DateUtils.getStartTime(start), DateUtils.getEndTime(end),
                    new ArrayList<>(deviceIds), dataTypeId, "DATE", classifyIds);
        } else {
            throw new ArithmeticException("不支持此类型");
        }
        dateStrChangeNew(dateType, res);
        return res.stream().map(m -> {
            if (m.getStatistic() != null) {
                m.setStatistic(m.getStatistic().setScale(4, RoundingMode.HALF_UP));
            }
            if (m.getCost() != null) {
                m.setCost(m.getCost().setScale(4, RoundingMode.HALF_UP));
            }
            return m;
        }).collect(Collectors.toList());
    }

    /**
     * 计算单位时间内（峰平谷）
     *
     * @param dateType
     * @param start
     * @param end
     * @param deviceIds
     * @param dataTypeId
     * @return
     */
    private List<ClassifyDeviceEleDTO> getDeviceDateType(String dateType, LocalDate start, LocalDate end, Set<String> deviceIds, String dataTypeId, List<String> classifyIds) {
        List<ClassifyDeviceEleDTO> res = new ArrayList<>();
        if (dataVerify(start)) {
            return res;
        }
        long days = ChronoUnit.DAYS.between(start, end);
        // 不同类型，统计分组不同
        if (dateType.equals(DateType.DAY)) {
            res = baseMapper.getDeviceTypeEle(DateUtils.getStartTime(start), DateUtils.getEndTime(start),
                    new ArrayList<>(deviceIds), dataTypeId, "HOUR", classifyIds);
        } else if (dateType.equals(DateType.WEEK)) {
            res = baseMapper.getDeviceTypeEle(DateUtils.getStartTime(start), DateUtils.getEndTime(start.plusDays(6)),
                    new ArrayList<>(deviceIds), dataTypeId, "DATE", classifyIds);
        } else if (dateType.equals(DateType.MONTH)) {
            res = baseMapper.getDeviceTypeEle(DateUtils.getStartTime(start), DateUtils.getEndTime(YearMonth.from(start).atEndOfMonth()),
                    new ArrayList<>(deviceIds), dataTypeId, "DATE", classifyIds);
        } else if (dateType.equals(DateType.YEAR)) {
            res = baseMapper.getDeviceTypeEle(DateUtils.getStartTime(start), DateUtils.getEndTime(LocalDate.of(start.getYear(), 12,
                    31)), new ArrayList<>(deviceIds), dataTypeId, "MONTH", classifyIds);
        } else if (dateType.equals(DateType.HIS_YEAR)) {
            int year = start.getYear();
            while (year <= end.getYear() && year <= LocalDate.now().getYear()) {
                List<ClassifyDeviceEleDTO> tmp = baseMapper.getDeviceTypeEle(DateUtils.getStartTime(start), DateUtils.getEndTime(LocalDate.of(end.getYear(),
                        12, 31)), new ArrayList<>(deviceIds), dataTypeId, "YEAR", classifyIds);
                res.add(tmp.get(0));
                year++;
            }
        } else if (dateType.equals(DateType.CUSTOM)) {
            // 天最多支持90天
//            if (days > 90) {
//                throw new ConditionException("天统计最多90天");
//            }
            res = baseMapper.getDeviceTypeEle(DateUtils.getStartTime(start), DateUtils.getEndTime(end),
                    new ArrayList<>(deviceIds), dataTypeId, "DATE", classifyIds);
        } else {
            throw new ArithmeticException("不支持此类型");
        }
        dateStrChangeNewEle(dateType, res);
        return res;
    }

    /**
     * 获取时间段内设备属性的和值（按设备统计，实时值）
     *
     * @param dateType
     * @param start
     * @param end
     * @param deviceIds
     * @param dataTypeId
     * @return
     */
    @Override
    public List<DeviceMeasureDateGroupDto> getDeviceAvg(String dateType, LocalDate start, LocalDate end, Set<String> deviceIds, String dataTypeId, List<String> classifyIds) {
        List<DeviceMeasureDateGroupDto> res = new ArrayList<>();
        if (dataVerify(start)) {
            return res;
        }
        long days = ChronoUnit.DAYS.between(start, end);
        // 不同类型，统计分组不同
        if (dateType.equals(DateType.DAY)) {
            res = baseMapper.getDeviceHourAvg(start.getYear(), DateUtils.getStartTime(start), DateUtils.getEndTime(start),
                    new ArrayList<>(deviceIds), dataTypeId, "HOUR", classifyIds);
        } else if (dateType.equals(DateType.DAY_HALF_HOUR)) {
            res = baseMapper.getDeviceHalfHourAvg(start.getYear(), DateUtils.getStartTime(start), DateUtils.getEndTime(start),
                    new ArrayList<>(deviceIds), dataTypeId, "HOUR", classifyIds);
        } else if (dateType.equals(DateType.WEEK)) {
            res = baseMapper.getDeviceAvg(start.getYear(), DateUtils.getStartTime(start), DateUtils.getEndTime(start.plusDays(6)),
                    new ArrayList<>(deviceIds), dataTypeId, "DATE", classifyIds);
        } else if (dateType.equals(DateType.MONTH)) {
            res = baseMapper.getDeviceAvg(start.getYear(), DateUtils.getStartTime(start), DateUtils.getEndTime(YearMonth.from(start).atEndOfMonth()),
                    new ArrayList<>(deviceIds), dataTypeId, "DATE", classifyIds);
        } else if (dateType.equals(DateType.YEAR)) {
            res = baseMapper.getDeviceAvg(start.getYear(), DateUtils.getStartTime(start), DateUtils.getEndTime(LocalDate.of(start.getYear(), 12,
                    31)), new ArrayList<>(deviceIds), dataTypeId, "MONTH", classifyIds);
        } else if (dateType.equals(DateType.HIS_YEAR)) {
            int year = start.getYear();
            while (year <= end.getYear() && year <= LocalDate.now().getYear()) {
                List<DeviceMeasureDateGroupDto> tmp = baseMapper.getDeviceAvg(year, DateUtils.getStartTime(start), DateUtils.getEndTime(LocalDate.of(end.getYear(),
                        12, 31)), new ArrayList<>(deviceIds), dataTypeId, "YEAR", classifyIds);
                res.add(tmp.get(0));
                year++;
            }
        } else if (dateType.equals(DateType.CUSTOM)) {
            // 天最多支持90天
//            if (days > 90) {
//                throw new ConditionException("天统计最多90天");
//            }
            res = baseMapper.getDeviceAvg(start.getYear(), DateUtils.getStartTime(start), DateUtils.getEndTime(end),
                    new ArrayList<>(deviceIds), dataTypeId, "DATE", classifyIds);
        } else {
            throw new ArithmeticException("不支持此类型");
        }
        dateStrChangeNew(dateType, res);
        return res;
    }

    /**
     * 数据校验
     *
     * @param start
     */
    private boolean dataVerify(LocalDate start) {
        return start.getYear() < startYear;
    }


    @Override
    public PageResult<DeviceMeasureDataVO> pageByDevice(DeviceMeasureDataPageParam param) {
        PageResult<DeviceMeasureData> result = customPage(param, (a, p) -> baseMapper.queryPageListByDeviceId(a, p));
        if (CollectionUtil.isEmpty(result.getList())) {
            return new PageResult<>(0L, new ArrayList<>(0));
        }

        List<DevicePropertyEntity> properties = devicePropertyService.listByDeviceId(param.getDeviceId());
        Map<String, DevicePropertyEntity> propertyMap = properties.stream().collect(Collectors.toMap(DevicePropertyEntity::getDataTypeId, (a) -> a));
        Set<String> unitIdSet = result.getList().stream().map(DeviceMeasureData::getUnitId).collect(Collectors.toSet());
        List<DataUnitEntity> units = dataUnitService.listByIdList(unitIdSet);
        Map<String, DataUnitEntity> unitMap = units.stream().collect(Collectors.toMap(DataUnitEntity::getId, (a) -> a));
        List<DeviceMeasureDataVO> list = result.getList().stream().map((a) -> {
            DevicePropertyEntity property = propertyMap.get(a.getDataTypeId());
            DataUnitEntity unit = unitMap.get(a.getUnitId());
            DeviceMeasureDataVO vo = DeviceMeasureDataVO.builder().id(a.getId())
                    .propertyName(Objects.nonNull(property) ? property.getName() : null)
                    .unitName(Objects.nonNull(unit) ? unit.getName() : null)
                    .measureValue(String.valueOf(a.getMeasureValue()))
                    .measureTime(a.getMeasureTime())
                    .deviceName(a.getDeviceName())
                    .devicCode(a.getDeviceCode())
                    .build();

            //处理颜色、运行状态
            DataTypeEntity dataTypeEntity = dataTypeService.getById(a.getDataTypeId());
            if (DictCodeEnum.COLOR.getCode().equals(dataTypeEntity.getCode())
                    || DictCodeEnum.OPERATIONAL_STATUS.getCode().equals(dataTypeEntity.getCode())) {
                //颜色类型 或者 运行状态类型
                DictItem dictItem = dictItemService.getById(a.getMeasureValue());
                vo.setMeasureValue(dictItem.getItemName());
            }

            return vo;
        }).toList();
        return new PageResult<>(result.getTotal(), list);
    }

    @Override
    public BigDecimal sumIncrementValByTypeAndDataType(String deviceType, String dataType, LocalDateTime startDate, LocalDateTime endDate) {
        if (dataVerify(startDate.toLocalDate())) {
            return BigDecimal.ZERO;
        }
        return null;
    }

    /**
     * 查询一段时间内检测数据
     *
     * @param startTime
     * @param endTime
     * @param ids
     * @return
     */
    @Override
    public List<DeviceMeasureData> list(Date startTime, Date endTime, List<String> ids) {
        QueryWrapper<DeviceMeasureData> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().
                between(DeviceMeasureData::getMeasureTime, startTime, endTime).
                in(DeviceMeasureData::getDeviceId, ids);
        return baseMapper.selectList(queryWrapper);
    }

    /**
     * 查询一段时间内检测数据
     *
     * @param startTime
     * @param endTime
     * @param ids
     * @return
     */
    @Override
    public List<DeviceMeasureDateGroupDto> listDeviceHour(String startDay, String endDay, String classifyId, Set<String> deviceIdSet, String dataTypeId) {

        List<String> classifyIds = new ArrayList<>();
        classifyIds.add(classifyId);
        List<DeviceMeasureDateGroupDto> deviceMeasureDateGroupDtoList = baseMapper.listDeviceHour(DateUtils.getStartTime(LocalDate.parse(startDay)), DateUtils.getEndTime(LocalDate.parse(endDay)), deviceIdSet, dataTypeId, classifyIds);
        deviceMeasureDateGroupDtoList = deviceMeasureDateGroupDtoList.stream().map(m -> {
            m.setDayStr(roundToHalfHour(m.getDayStr()));
            return m;
        }).collect(Collectors.toList());

        return deviceMeasureDateGroupDtoList;
    }


    /**
     * 时间取整
     *
     * @param dateTimeString
     * @return
     */
    public static String roundToHalfHour(String dateTimeString) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date dateExecute = null;
        try {
            dateExecute = sdf.parse(dateTimeString);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(dateExecute);


        int minutes = calendar.get(Calendar.MINUTE);

        // 如果分钟数是30，直接使用当前时间
        if (minutes >= 30) {
            calendar.set(Calendar.MINUTE, 30);
            calendar.set(Calendar.SECOND, 0);
        } else {
            // 如果分钟数不是30，则向下取整到0或30
            calendar.set(Calendar.MINUTE, minutes >= 30 ? 30 : 0);
            calendar.set(Calendar.SECOND, 0);
        }

        calendar.getTime();


        String dateString = sdf.format(calendar.getTime());
        return dateString;
    }


    @Override
    public List<DeviceMeasureData> getCurrentValByDeviceIds(List<String> deviceIds) {
        QueryWrapper<DeviceMeasureData> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().
                in(DeviceMeasureData::getDeviceId, deviceIds);
        return baseMapper.selectList(queryWrapper);
    }

    @Override
    public List<DeviceMeasureDataDayEntity> getDayDataByDate(LocalDate date) {
        QueryWrapper<DeviceMeasureDataDayEntity> param = new QueryWrapper<>();
        param.lambda().eq(DeviceMeasureDataDayEntity::getMeasureTime, date);
        return deviceMeasureDataDayMapper.selectList(param);
    }

    @Override
    public List<DeviceMeasureDataIncrementHour> getDayHourDataByDate(LocalDateTime dateTime) {
        QueryWrapper<DeviceMeasureDataIncrementHour> param = new QueryWrapper<>();
        param.lambda().eq(DeviceMeasureDataIncrementHour::getMeasureTime, dateTime);
        return deviceMeasureDataIncrementHourMapper.selectList(param);
    }

    @Override
    public Long countDayDataByDate(LocalDate date) {
        QueryWrapper<DeviceMeasureDataDayEntity> param = new QueryWrapper<>();
        param.lambda().eq(DeviceMeasureDataDayEntity::getMeasureTime, date);
        return deviceMeasureDataDayMapper.selectCount(param);
    }

    @Override
    public Long countDayHourDataByDate(LocalDateTime date) {
        QueryWrapper<DeviceMeasureDataIncrementHour> param = new QueryWrapper<>();
        param.lambda().eq(DeviceMeasureDataIncrementHour::getMeasureTime, date);
        return deviceMeasureDataIncrementHourMapper.selectCount(param);
    }

    @Override
    public void batchSave(List<DeviceMeasureDataDayEntity> insertDataList) {
        deviceMeasureDataDayMapper.btpBatchInsert(insertDataList);
    }

    @Override
    public PageResult<DeviceMeasureDataVO> measureDataPageList(DeviceMeasureDataQParam param) {
        if (DeviceTreeVO.DEVICE_TYPE.equals(param.getNodeType())) {
            param.setTypeCode(param.getNodeId());
        } else if (DeviceTreeVO.DEVICE.equals(param.getNodeType())) {
            param.setDeviceId(param.getNodeId());
        }
        PageResult<DeviceMeasureDataExtendDTO> result = customPage(param, (a, p) -> baseMapper.measureDataPageList(a, p));
        if (CollectionUtil.isEmpty(result.getList())) {
            return new PageResult<>(0L, new ArrayList<>(0));
        }
        List<DevicePropertyEntity> properties = devicePropertyService.listByDeviceIds(result.getList().stream().map(DeviceMeasureDataExtendDTO::getDeviceId).collect(Collectors.toSet()));
        Map<String, DevicePropertyEntity> propertyMap = properties.stream().collect(Collectors
                .toMap(DevicePropertyEntity::getDataTypeId, (a) -> a, (v1, v2) -> v2));
        Set<String> unitIdSet = result.getList().stream().map(DeviceMeasureDataExtendDTO::getUnitId).collect(Collectors.toSet());
        List<DataUnitEntity> units = dataUnitService.listByIdList(unitIdSet);

        Map<String, DataUnitEntity> unitMap = units.stream().collect(Collectors.toMap(DataUnitEntity::getId, (a) -> a));
        List<DeviceMeasureDataVO> list = result.getList().stream().map((a) -> {
            DevicePropertyEntity property = propertyMap.get(a.getDataTypeId());
            DataUnitEntity unit = unitMap.get(a.getUnitId());
            DeviceMeasureDataVO vo = DeviceMeasureDataVO.builder().id(a.getId())
                    .propertyName(Objects.nonNull(property) ? property.getName() : null)
                    .unitName(Objects.nonNull(unit) ? unit.getName() : null)
                    .measureValue(String.valueOf(a.getMeasureValue()))
                    .measureTime(a.getMeasureTime())
                    .devicCode(a.getDeviceCode())
                    .deviceName(a.getDeviceName())
                    .updateUserId(a.getUpdateUserId())
                    .updateUserName(Optional.ofNullable(userService.loadById(a.getUpdateUserId()))
                            .map(User::getUserName).orElse(""))
                    .updateTime(a.getUpdateTime())
                    .build();

            //处理颜色、运行状态
            DataTypeEntity dataTypeEntity = dataTypeService.getById(a.getDataTypeId());

            if (dataTypeEntity.getGroupLevel1Name().equals(BoardConstant.DEVICE_EXTEND_GROUP_NAME) && a.getMeasureTime() == null
                    && (DictCodeEnum.COLOR.getCode().equals(dataTypeEntity.getCode())
                    || DictCodeEnum.OPERATIONAL_STATUS.getCode().equals(dataTypeEntity.getCode()))) {
                if (DictCodeEnum.OPERATIONAL_STATUS.getCode().equals(dataTypeEntity.getCode())) {
                    // 获取设备运行状态
                    List<DictItem> statusItems = dictItemService.getByDictCode(DictCodeEnum.OPERATIONAL_STATUS.getCode());
                    Map<String, String> statusMap = statusItems.stream().collect(Collectors.toMap(DictItem::getItemCode, DictItem::getItemName));
                    // 获取设备状态
                    DeviceEntity deviceEntity = deviceService.getById(a.getDeviceId());
                    vo.setPropertyName(dataTypeEntity.getName());
                    vo.setMeasureValue(statusMap.get(DeviceStatusDictItemEnum.getOnlineStatusStr(deviceEntity.getOnlineStatus())));
                } else {
                    //颜色类型
                    DictItem dictItem = dictItemService.getById(a.getMeasureValue());
                    vo.setMeasureValue(dictItem.getItemName());
                }
            }

            return vo;
        }).toList();
        return new PageResult<>(result.getTotal(), list);
    }

    @Override
    public List<ClassifyDeviceEleDTO> getDeviceTypeEle(String dateType, LocalDate start, LocalDate end, Set<String> deviceIds, String dataTypeId, List<String> classifyIds) {
        return getDeviceDateType(dateType, start, end, deviceIds, dataTypeId, classifyIds);
    }


    private DevicePropertyService devicePropertyService;

    @Autowired
    public void setDevicePropertyService(DevicePropertyService devicePropertyService) {
        this.devicePropertyService = devicePropertyService;
    }

    private DataUnitService dataUnitService;

    @Autowired
    public void setDataUnitService(DataUnitService dataUnitService) {
        this.dataUnitService = dataUnitService;
    }

    private DataTypeService dataTypeService;

    @Autowired
    public void setDataTypeService(DataTypeService dataTypeService) {
        this.dataTypeService = dataTypeService;
    }

    private DictItemService dictItemService;

    @Autowired
    public void setDictItemService(DictItemService dictItemService) {
        this.dictItemService = dictItemService;
    }
}
